import { EntityManager, MikroORM} from '@mikro-orm/mysql';
import { InjectEntityManager, InjectMikroORM } from '@mikro-orm/nestjs';
import { Controller, Get, Inject, Post, Query, Req } from '@nestjs/common';
import { JobTasks } from "@entities/JobTasks";
import dayjs from 'dayjs';
import { JsonApiResponse } from '@utils/json.api.response';
import { JobProjectJobs } from "@entities/JobProjectJobs";
import { JobTaskVO } from "@databases/vo/JobTasksVO";
import { knexPrefix, prefix } from "@databases/vo/dao-helper";
import { JobProjectJobskVO } from "@databases/vo/JobProjectJobsVO";
import { UserskVO } from "@databases/vo/UserVO";
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { Users } from "@entities/Users";
import { wrap } from '@mikro-orm/core';
import { JobProjectSources } from "@entities/JobProjectSources";
//import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { knext } from 'knext';
import { OrderJobEnrolls } from '@databases/entities/OrderJobEnrolls';
import { JobTasksPictures } from '@databases/entities/JobTasksPictures';

@ApiTags('(游客) 兼职-任务')
@Controller('task')
export class TaskController {
    constructor(
        @InjectMikroORM('zp')
        private readonly orm : MikroORM,
        @InjectEntityManager('zp')
        private readonly em : EntityManager,
        @Inject(CACHE_MANAGER) 
        private cache: Cache
    ){}
    
    @ApiOperation({summary:'获取日历数据 (分类M)'})
    @Get('itinerary')
    public async itinerary(@Req() request : Request, @Query() querys) {
        const source_id = querys.source_id || '0';
        
        const nowdate = dayjs().format('YYYY-MM-DD'); //date('Y-m-d');import dayjs from 'dayjs';
        //const nowTime = dayjs().format('HH:mm');

        const itinerarysQuery = this.em.qb(JobTasks)
        .select(['startDate',this.em.raw('count(*) as count')])
        .where({startDate:{$gte:nowdate}})
        .groupBy('startDate')
        .orderBy({startDate:'ASC'});
        
        if(querys.source_id) itinerarysQuery.andWhere({source:source_id});

        const itinerary = await itinerarysQuery.execute();

        let today =  await this.em.qb(JobTasks,'job_tasks')
        .leftJoin('jobs','jobs')
        .select(['start_date as start_date',this.em.raw('COUNT(jobs.id) as job_count')])
        .where({$and:[{'start_date': nowdate},{'jobs.start_time':{$gte:'12:00'}}]})
        .groupBy('start_date')
        .orderBy({'start_date':'asc'})
        .execute();
 
        return JsonApiResponse.new({today,itinerary});        
    }

    @ApiOperation({summary:'获取当日活动任务 (列表 L)'})
    @Get('list')
    public async dayList(@Req() request : Request, @Query() querys) {

        const url = request.url

        ///api/common/job/task/list?start_date=2023-09-23&page=1&size=10
        ///api/common/job/task/list?start_date=2023-09-23&page=1&size=10

        let result = null;//await this.cache.get(url)

        if(result)
            return JsonApiResponse.new(result)

        const nowdate = dayjs().format('YYYY-MM-DD');
        const start_date = querys.start_date || nowdate;
        const nowTime = dayjs().format('HH:mm');
        const noPage =  querys.page || 1
        const sizePage = querys.size || 1
        
        const knex = knext(this);

        //========= 按项目去重(source_id)查询,每个项目只显示(最新且有未到期任务岗位)的一条。
        
        //-- 未到期任务(岗位统计),子查询 KNEX
        const jobs_count = knex
        .fromORM(JobProjectJobs,'jobs')
        //.as('jobs_count')
        .count('jobs.id')
        .where('jobs.task_id',knex.ref('tasks.id'))
        
        if(new Date(start_date) <= new Date())
        {
            jobs_count.where("start_time",">",nowTime)
        }

         //-- 未到期任务统计,子查询
        const query = knex
        .fromORM(JobTasks,'tasks')
        .select(['source_id',knex.raw('MAX(created_at) as newest_at')])
        .where('start_date',start_date) //查询指定日期的任务
        .where( 0,'<',jobs_count) //未到期任务岗位统计 大于 0
        .groupBy(['source_id']) // 项目去重
        .orderByRaw(knex.raw('MAX(created_at) DESC')) // 去重取最值
        .paginate(noPage,sizePage)

        const whats = await query.populate();

        const newest_at = whats.map(o=>o.newest_at);
        const source_ids = whats.map((o=>o.source_id));

        //-- 未到期任务(岗位统计),子查询 mikro

        let tasks : any = knex
        .fromORM(JobTasks,'tasks')
        .select(
            ...knexPrefix(JobTaskVO.baseInfo()),
            'created_at',
            knex
            .fromORM(JobProjectJobs)
            .select(knex.raw('COUNT(*)'))
            .where("task_id",knex.ref('tasks.id'))
            .as('jobs_count'),
            //
            knex
            .fromORM(JobProjectJobs)
            .select(knex.raw('SUM(num)'))
            .where("task_id",knex.ref('tasks.id'))
            .as('recruit_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .as('enrolls_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('assigned_job_at')
            .as('comfirm_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('sign_up_at')
            .as('sign_up_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('sign_down_at')
            .as('sign_down_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('verified_at')
            .as('verified_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('give_salary_at')
            .as('give_salary_count')
        )
        .where('start_date',start_date)  // 指定日期
        .whereIn('source_id',source_ids) //过滤后的项目标识 - 创建者
        .whereIn('created_at',newest_at) // 过滤后的项目标识 - 最新日期
        .andWhere(0,'<', jobs_count )  //还有活动岗位的
        .andWhere({is_public:1})
        //查询开始日期为当天的活动
        .orderBy('created_at','DESC')
        .withEntity(JobProjectSources,'source')
        .withEntity(JobProjectJobs,'jobs',(qb)=>{
            qb.onlySelect(
                ...knexPrefix(JobProjectJobskVO.baseInfo()),
            )
        })
        .withEntity(Users,'creator',(qb)=>{
            qb.onlySelect(
                ...knexPrefix(UserskVO.baseInfo()),
            )
        })

        tasks = await tasks.populate()

        tasks = tasks.map(task=>{
            task.jobs_count = task.jobs_count ? task.jobs_count : 1
            task.title = task.title || task.source.title;
            return task
        })

        //await this.cache.set(url,tasks,1000*1000)
        //let no = await this.cache.get(url)

        return JsonApiResponse.new(tasks);
    } 

    @ApiOperation({summary:'获取当日活动任务 (列表 L)'})
    @Get('list/public')
    public async publicDayList(@Req() request : Request, @Query() querys) {

        const url = request.url

        ///api/common/job/task/list?start_date=2023-09-23&page=1&size=10
        ///api/common/job/task/list?start_date=2023-09-23&page=1&size=10

        let result = null;//await this.cache.get(url)

        if(result)
            return JsonApiResponse.new(result)

        const nowdate = dayjs().format('YYYY-MM-DD');
        const start_date = querys.start_date || nowdate;
        const nowTime = dayjs().format('HH:mm');
        const noPage =  querys.page || 1
        const sizePage = querys.size || 1
        
        const knex = knext(this);

        //========= 按项目去重(source_id)查询,每个项目只显示(最新且有未到期任务岗位)的一条。
        
        //-- 未到期任务(岗位统计),子查询 KNEX
        const jobs_count = knex
        .fromORM(JobProjectJobs,'jobs')
        //.as('jobs_count')
        .count('jobs.id')
        .where('jobs.task_id',knex.ref('tasks.id'))
        
        if(new Date(start_date) <= new Date())
        {
            jobs_count.where("start_time",">",nowTime)
        }

         //-- 未到期任务统计,子查询
        const query = knex
        .fromORM(JobTasks,'tasks')
        .select(['source_id',knex.raw('MAX(created_at) as newest_at')])
        .where('start_date',start_date) //查询指定日期的任务
        //.where( 0,'<',jobs_count) //未到期任务岗位统计 大于 0
        .groupBy(['source_id']) // 项目去重
        .orderByRaw(knex.raw('MAX(created_at) DESC')) // 去重取最值
        .paginate(noPage,sizePage)

        const whats = await query.populate();

        const newest_at = whats.map(o=>o.newest_at);
        const source_ids = whats.map((o=>o.source_id));

        //-- 未到期任务(岗位统计),子查询 mikro

        let tasks : any = knex
        .fromORM(JobTasks,'tasks')
        .select(
            ...knexPrefix(JobTaskVO.baseInfo()),
            'created_at',
            knex
            .fromORM(JobProjectJobs)
            .select(knex.raw('COUNT(*)'))
            .where("task_id",knex.ref('tasks.id'))
            .as('jobs_count'),
            //
            knex
            .fromORM(JobProjectJobs)
            .select(knex.raw('SUM(num)'))
            .where("task_id",knex.ref('tasks.id'))
            .as('recruit_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .as('enrolls_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('assigned_job_at')
            .as('comfirm_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('sign_up_at')
            .as('sign_up_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('sign_down_at')
            .as('sign_down_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('verified_at')
            .as('verified_count'),
            //
            knex
            .fromORM(OrderJobEnrolls)
            .select(knex.raw('COUNT(*)'))
            .where("job_task_id",knex.ref('tasks.id'))
            .whereNotNull('give_salary_at')
            .as('give_salary_count')
        )
        .where('start_date',start_date)  // 指定日期
        //.whereIn('source_id',source_ids) //过滤后的项目标识 - 创建者
        //.whereIn('created_at',newest_at) // 过滤后的项目标识 - 最新日期
        //.andWhere(0,'<', jobs_count )  //还有活动岗位的
        .andWhere({is_public:1})
        //查询开始日期为当天的活动
        //.orderBy('created_at','DESC')
        .withEntity(JobProjectSources,'source')
        .withEntity(JobProjectJobs,'jobs',(qb)=>{
            qb.onlySelect(
                ...knexPrefix(JobProjectJobskVO.baseInfo()),
            )
        })
        .withEntity(Users,'creator',(qb)=>{
            qb.onlySelect(
                ...knexPrefix(UserskVO.baseInfo()),
            )
        })

        tasks = await tasks.populate()

        tasks = tasks.map(task=>{
            task.jobs_count = task.jobs_count ? task.jobs_count : 1
            task.title = task.title || task.source.title;
            return task
        })

        //await this.cache.set(url,tasks,1000*1000)
        //let no = await this.cache.get(url)

        return JsonApiResponse.new(tasks);
    } 
    
    @ApiOperation({summary:'获取任务详情 (单例 S)'})
    @Get('details')
    public async details(@Req() request : Request, @Query() querys) {
        const task_id = querys.task_id || 1;

        let task = await this.em.qb(JobTasks,'tasks')
        .select([
            ...JobTaskVO.baseInfo(),
            'created_at',
            'creator_id',
            'source_id',
            this.em.qb(JobProjectJobs,'jobs')
            .count('jobs.id',true)
            .where({'jobs.task_id':this.em.getKnex().ref('tasks.id')})
            .as('jobs_count')
        ])
        .where({'tasks.id': task_id})
        .getSingleResult()

        await this.em.populate(task,[
            'jobs',
            'source',
            'creator'
        ],{
            fields: [
                ...prefix('creator',UserskVO.baseInfo())
            ]
        })

        return JsonApiResponse.new(task);

        // const projects = await this.em.qb(JobProjectSources)
        // .select(['id','creatorId'])
        // .cache(false)
        // .where({'id':22})
        // .getResult();
    
        // const nowdate = dayjs().format('YYYY-MM-DD');

        // let projectsPopulated = await this.em.populate(projects,
        //     ['jobTasks','jobTasks.jobProjectJobs'],
        //     { 
        //         fields: [
        //             ...prefix('jobTasks',JobTaskVO.baseInfo()),
        //             ...prefix('jobTasks.jobProjectJobs',JobProjectJobskVO.baseInfo())
        //         ],
        //         where:{ 
        //             'jobTasks': {"startDate" : {$gte : nowdate}},
        //             'jobTasks.jobProjectJobs' : {"startTime" : "12:00"}
        //         }
        // });

        // let llvm = projectsPopulated.map(w=>wrap(w,true).toObject());
        // return llvm;
    } 

    @Get('put')
    public async addPicture()
    {
        let knex = knext(this)
        await knex.fromORM(JobTasksPictures)
        .insert({task_id:2446,type:'verify',url:'http://192.168.1.6:9000/common/2024-03-20%2003%3A33%3A27.png'})
    }
}
 